#include <ClanLib/display.h>
#include "MainLoop.h"
#include "EqualTemperament.h"

MainLoop::MainLoop()
	: piano_engine(new EqualTemperament())
{
}

void MainLoop::start(const std::vector<CL_String> &args)
{
	quit = false;

	try
	{
		CL_DisplayWindow window("MusicLife", 640, 480);
		CL_Slot slots[] = {
			window.sig_window_close().connect(this, &MainLoop::on_window_close),
			window.get_ic().get_keyboard().sig_key_up().connect(this, &MainLoop::on_input_up),
			window.get_ic().get_keyboard().sig_key_down().connect(this, &MainLoop::on_input_down)
		};
		CL_GraphicContext gc = window.get_gc();

		while (!quit)
		{
			gc.clear(CL_Colorf(0.0f,0.0f,0.0f));
			window.flip();

			CL_KeepAlive::process();
		}
	}
	catch(CL_Exception &exception)
	{
		CL_Console::write_line("Exception caught: " + exception.get_message_and_stack_trace());
		CL_Console::wait_for_key();
	}
}

static bool get_note_for_key(CL_InputEvent const& key, int* note)
{
	int id;
	switch(key.id) // first, do some remapping for convenience
	{
		case 186: id = ';'; break;
		case 187: id = '='; break;
		case 188: id = ','; break;
		case 190: id = '.'; break;
		case 191: id = '/'; break;
		case 219: id = '['; break;
		case 221: id = ']'; break;
		default: id = key.id; break;
	}

	std::map<int, int> keyMapping;
	keyMapping['Z'] = 0; keyMapping['S'] = 1; keyMapping['X'] = 2; keyMapping['D'] = 3; keyMapping['C'] = 4; keyMapping['V'] = 5;
	keyMapping['G'] = 6; keyMapping['B'] = 7; keyMapping['H'] = 8; keyMapping['N'] = 9; keyMapping['J'] = 10; keyMapping['M'] = 11;
	keyMapping[','] = 12; keyMapping['L'] = 13; keyMapping['.'] = 14; keyMapping[';'] = 15; keyMapping['/'] = 16; keyMapping['Q'] = 12;
	keyMapping['2'] = 13; keyMapping['W'] = 14; keyMapping['3'] = 15; keyMapping['E'] = 16; keyMapping['R'] = 17; keyMapping['5'] = 18;
	keyMapping['T'] = 19; keyMapping['6'] = 20; keyMapping['Y'] = 21; keyMapping['7'] = 22; keyMapping['U'] = 23; keyMapping['I'] = 24;
	keyMapping['9'] = 25; keyMapping['O'] = 26; keyMapping['0'] = 27; keyMapping['P'] = 28; keyMapping['['] = 29; keyMapping['='] = 30;
	keyMapping[']'] = 31;
	if(keyMapping.find(id) == keyMapping.end()) return false;
	*note = keyMapping[id];
	return true;
}

void MainLoop::on_input_up(const CL_InputEvent &key, const CL_InputState &state)
{
	if(key.id == CL_KEY_ESCAPE)
	{
		quit = true;
	}

	int note_id;
	if(get_note_for_key(key, &note_id))
	{
		piano_engine.begin_note_release(note_id);
	}
}

void MainLoop::on_input_down(const CL_InputEvent &key, const CL_InputState &state)
{
	if(key.repeat_count > 0) return;
	int note_id;
	if(get_note_for_key(key, &note_id))
	{
		piano_engine.begin_playing_note(note_id);
	}
}

void MainLoop::on_window_close()
{
	quit = true;
}
